<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      td {
        position: relative;
      }
      td .ok-btn {
        position: absolute;
        bottom: -20px;
        right: 50px;
        z-index: 999;
      }
      td .cancel-btn {
        position: absolute;
        bottom: -20px;
        right: 0;
        z-index: 999;
      }
    </style>
  </head>
  <body>
    <table border="1">
      <thead>
        <tr>
          <th>姓名</th>
          <th>年龄</th>
          <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td data-action="edit">jack</td>
          <td data-action="edit">20</td>
          <td data-action="edit">jack@qq.com</td>
        </tr>
        <tr>
          <td>lili</td>
          <td>20</td>
          <td>lili@qq.com</td>
        </tr>
      </tbody>
    </table>
    <script>
      // 记录当前是否有单元格被编辑
      const status = {
        flag: false, // 当前没有正在编辑的单元格
        old: "",
        cell: null,
      };
      document.onclick = function (e) {
        const target = e.target;
        const action = target.dataset.action;

        if (action === "edit") {
          // 保存单元格对象，方便后续事件使用
          status.cell = target;
          // 如果有正在被编辑的单元格，下面代码不执行
          if (status.flag === true) return;
          // 保存当前单元格的内容
          const tdContent = target.innerText;
          status.old = tdContent; //将原来的内容备份
          // 创建输入框 ， 阻止冒泡，将当前内容放入input中
          const input = `
          <input id="cellInput" onclick="event.stopPropagation();" value="${tdContent}" />
          <button class="ok-btn" data-action="ok">确定</button>
          <button class="cancel-btn"  data-action="cancel">取消</button>
          `;
          // 使用 input 替换单元格
          target.innerHTML = input;
          // 获取焦点
          cellInput.focus();
          // 有单元格在编辑，其他单元格不能进入编辑状态
          status.flag = true;
        }

        // 确定
        if (action === "ok") {
          status.cell.innerText = cellInput.value;
          status.flag = false;
        }

        // 取消
        if (action === "cancel") {
          status.cell.innerText = status.old;
          status.flag = false;
        }
      };
    </script>
  </body>
</html>
